#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include "Mutex.hpp"

// using namespace MutexModule;
// int ticket = 1000;


// class ThreadData
// {
// public:
//     ThreadData(const std::string& s, Mutex& lock)
//         :lockp(&lock)
//         ,name(s)
//     {}

//     ~ThreadData()
//     {}

//     Mutex* lockp;
//     std::string name;
// };

// void* thread_func(void* args)
// {
//     ThreadData* ptd = static_cast<ThreadData*>(args);
//     while (1)
//     {
//         LockGuard guard(*ptd->lockp);
//         if(ticket > 0)
//         {
//             usleep(1000);
//             ticket--;
//             std::cout << ptd->name << " get ticket, ticket left: " << ticket << std::endl;
//             //ptd->lockp->Unlock();
//         }
//         else{
//             //ptd->lockp->Unlock();
//             break;
//         }
//     }
//     return nullptr; 
// }

// int main()
// {
//     pthread_t tids[4];
//     Mutex lock;
//     for(int i = 0; i < 4; i++)
//     {
//         std::string s = "thread-" + std::to_string(i);
//         ThreadData* td = new ThreadData(s, lock);
//         pthread_create(&tids[i], nullptr, thread_func, (void *)td);
//     }

//     for(int i = 0; i < 4; i++)
//     {
//         pthread_join(tids[i], nullptr);
//     }
//     return 0;
// }

// class ThreadData
// {
// public:
//     ThreadData(const std::string& s, Mutex& lock)
//         :lockp(&lock)
//         ,name(s)
//     {}

//     ~ThreadData()
//     {}

//     Mutex* lockp;
//     std::string name;
// };

// void* thread_func(void* args)
// {
//     ThreadData* ptd = static_cast<ThreadData*>(args);
//     while (1)
//     {
//         ptd->lockp->Lock();
//         if(ticket > 0)
//         {
//             usleep(1000);
//             ticket--;
//             std::cout << ptd->name << " get ticket, ticket left: " << ticket << std::endl;
//             ptd->lockp->Unlock();
//         }
//         else{
//             ptd->lockp->Unlock();
//             break;
//         }
//     }
//     return nullptr; 
// }

// int main()
// {
//     pthread_t tids[4];
//     Mutex lock;
//     for(int i = 0; i < 4; i++)
//     {
//         std::string s = "thread-" + std::to_string(i);
//         ThreadData* td = new ThreadData(s, lock);
//         pthread_create(&tids[i], nullptr, thread_func, (void *)td);
//     }

//     for(int i = 0; i < 4; i++)
//     {
//         pthread_join(tids[i], nullptr);
//     }
//     return 0;
// }

// int ticket = 1000;
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;


// void* thread_func(void* args)
// {
//     std::string s = static_cast<const char*>(args);
//     while (1)
//     {
//         pthread_mutex_lock(&lock);
//         if(ticket > 0)
//         {
//             usleep(1000);
//             ticket--;
//             std::cout << s << " get ticket, ticket left: " << ticket << std::endl;
//             pthread_mutex_unlock(&lock);
//         }
//         else{
//             pthread_mutex_unlock(&lock);
//             break;
//         }
//     }
//     return nullptr;
    
// }

// int main()
// {
//     pthread_t tids[4];
//     for(int i = 0; i < 4; i++)
//     {
//         std::string s = "thread-" + std::to_string(i);
//         pthread_create(&tids[i], nullptr, thread_func, (void *)s.c_str());
//     }

//     for(int i = 0; i < 4; i++)
//     {
//         pthread_join(tids[i], nullptr);
//     }
//     return 0;
// }


int ticket = 1000;
//静态初始化一把锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* thread_func(void* args)
{
    std::string s = static_cast<const char*>(args);
    while (1)
    {
        //加锁
        pthread_mutex_lock(&mutex);
        if(ticket > 0)
        {
            usleep(1000);
            ticket--;
            std::cout << s << " get ticket, ticket left: " << ticket << std::endl;
            //解锁
            pthread_mutex_unlock(&mutex);
        }
        else{
            //解锁
            pthread_mutex_unlock(&mutex);
            break;
        }
    }
    return nullptr;
    
}

int main()
{
    pthread_t tids[4];
    for(int i = 0; i < 4; i++)
    {
        std::string s = "thread-" + std::to_string(i);
        pthread_create(&tids[i], nullptr, thread_func, (void *)s.c_str());
    }

    for(int i = 0; i < 4; i++)
    {
        pthread_join(tids[i], nullptr);
    }
    return 0;
}